package sword

import (
	"strings"
)

const CommaSpace = ","

type SqlBuilder struct {
	Tokens []string
}

func NewSqlBuilder() (qb *SqlBuilder) {
	qb = new(SqlBuilder)
	return qb
}

func (qb *SqlBuilder) Select(fields ...string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "SELECT", strings.Join(fields, CommaSpace))
	return qb
}

// From join the tables
func (qb *SqlBuilder) From(tables ...string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "FROM", strings.Join(tables, CommaSpace))
	return qb
}

func (qb *SqlBuilder) JoinOn(table ...string) *SqlBuilder {
	for _, v := range table {
		qb.Tokens = append(qb.Tokens, "JOIN", v)
	}
	return qb
}

// LeftJoin LEFT JOIN the table
func (qb *SqlBuilder) LeftJoinOn(table ...string) *SqlBuilder {
	for _, v := range table {
		qb.Tokens = append(qb.Tokens, "LEFT JOIN", v)
	}
	return qb
}

// RightJoin RIGHT JOIN the table
func (qb *SqlBuilder) RightJoinOn(table ...string) *SqlBuilder {
	for _, v := range table {
		qb.Tokens = append(qb.Tokens, "RIGHT JOIN", v)
	}
	return qb
}

func (qb *SqlBuilder) Where(cond ...string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "WHERE", strings.Join(cond, " and "))
	return qb
}

// OrderBy join the Order by fields
func (qb *SqlBuilder) OrderBy(fields ...string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "ORDER BY", strings.Join(fields, CommaSpace))
	return qb
}

// Limit join the limit num
func (qb *SqlBuilder) Limit(limit string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "LIMIT", limit)
	return qb
}

// Offset join the offset num
func (qb *SqlBuilder) Offset(offset string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "OFFSET", offset)
	return qb
}

// GroupBy join the Group by fields
func (qb *SqlBuilder) GroupBy(fields ...string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "GROUP BY", strings.Join(fields, CommaSpace))
	return qb
}

// Having join the Having cond
func (qb *SqlBuilder) Having(cond string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "HAVING", cond)
	return qb
}

// Update join the update table
func (qb *SqlBuilder) Update(tables ...string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "UPDATE", strings.Join(tables, CommaSpace))
	return qb
}

// Set join the set kv
func (qb *SqlBuilder) Set(kv ...string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "SET", strings.Join(kv, CommaSpace))
	return qb
}

// Delete join the Delete tables

// InsertInto join the insert SQL
func (qb *SqlBuilder) InsertInto(table string, fields ...string) *SqlBuilder {
	qb.Tokens = append(qb.Tokens, "INSERT INTO", table)
	if len(fields) != 0 {
		fieldsStr := strings.Join(fields, CommaSpace)
		qb.Tokens = append(qb.Tokens, "(`", fieldsStr, "`)")
	}
	return qb
}

// Values join the Values(vals)
func (qb *SqlBuilder) Values(vals ...string) *SqlBuilder {
	valsStr := strings.Join(vals, CommaSpace)
	qb.Tokens = append(qb.Tokens, "VALUES", "('", valsStr, "')")
	return qb
}

// Subquery join the sub as alias

// String join all Tokens
func (qb *SqlBuilder) String() string {
	return strings.Join(qb.Tokens, " ")
}
